package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.alibaba.fastjson.JSONArray;
import com.mysql.cj.exceptions.PasswordExpiredException;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.example.bean.Power;
import org.example.bean.Role;
import org.example.bean.User;
import org.example.config.JwtConfig;
import org.example.handler.*;
import org.example.mapper.PowerMapper;
import org.example.mapper.UserMapper;
import org.example.service.UserService;
import org.example.util.JsonResult;
import org.example.util.MD5Util;
import org.example.util.ResultTool;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Auther:Liu
 * @Testname:UserServiceImpl
 * @Date:2025/8/5 11:32
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private PowerMapper powerMapper;
    @Resource
    private HttpServletRequest request;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 分页
     *
     * @param page
     * @param size
     * @return
     */
    @Cacheable(cacheNames = "UserList",key ="#page")
    public JsonResult find(int page, int size) {
        IPage<User> iPage = new Page<>(page, size);
        List<User> list = list(iPage);
        iPage.setRecords(list);
        return ResultTool.success(iPage);
    }

    /**
     * 添加用户信息
     *
     * @param user
     * @return
     */
    @CacheEvict(cacheNames = "UserList",key = "#user.id",allEntries = true)
    public JsonResult saveUser(User user) {
        String s = MD5Util.encryptMD5(user.getPassword());
        user.setPassword(s);
        boolean b = save(user);
        if (!b) {
            throw new UserSaveException("添加用户失败");
        } else {
            return ResultTool.success("添加成功");
        }
    }

    /**
     * 检测姓名是否唯一
     *
     * @param username
     * @return
     */
    @Override
    public JsonResult findUserNameCount(String username) {
        int i = userMapper.findUserNameCount(username);
        if (i > 0) {
            throw new NameIsCreatedException("姓名已存在");
        } else {
            return ResultTool.success("姓名可使用");
        }
    }

    /**
     * 检测电话是否唯一
     *
     * @param phone
     * @return
     */
    @Override
    public JsonResult findUserPhoneCount(String phone) {
        int i = userMapper.findUserPhoneCount(phone);
        if (i > 0) {
            throw new PhoneIsCreatedException("电话已存在");
        } else {
            return ResultTool.success("电话可使用");
        }
    }

    /**
     * 检测邮箱是否唯一
     *
     * @param email
     * @return
     */
    @Override
    public JsonResult findUserEmailCount(String email) {
        int i = userMapper.findUserEmailCount(email);
        if (i > 0) {
            throw new EmailIsCreatedException("邮箱不可用");
        } else {
            return ResultTool.success("邮箱可使用");
        }
    }

    /**
     * 修改用户信息
     *
     * @param id
     * @param status
     * @return
     */
    @CacheEvict(cacheNames = "UserList",key = "#id",allEntries = true)
    public JsonResult changeStatus(String id, Integer status) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id);
        wrapper.set("status", status);
        boolean b = update(wrapper);
        if (!b) {
            throw new UserUpdateException("修改状态失败");
        } else {
            return ResultTool.success("修改状态成功");
        }
    }

    /**
     * 通过id查询一条用户信息
     *
     * @param id
     * @return
     */
    @Override
    public JsonResult findUserById(String id) {
        User byId = getById(id);
        return ResultTool.success(byId);
    }

    /**
     * 更新用户信息
     *
     * @param user
     * @return
     */
    @CachePut(cacheNames = "UserList",key = "#user.id")
    @CacheEvict(cacheNames = "UserList",key = "#user.id",allEntries = true)
    public JsonResult updateUser(User user) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", user.getId());
        wrapper.set("username", user.getUsername());
        wrapper.set("phone", user.getPhone());
        wrapper.set("email", user.getEmail());
        wrapper.set("address", user.getAddress());
        wrapper.set("status", user.getStatus());
        wrapper.set("update_time", LocalDate.now());
        boolean b = update(wrapper);
        if (!b) {
            throw new UserUpdateException("修改用户信息失败");
        } else {

////            将修改的数据加入Redis缓存中
//            ListOperations<String, String> ops = stringRedisTemplate.opsForList();
//            List<String> list = ops.range("UserList", 0, -1);
//            final int[] index = {0};
//            if (list!=null){
//                list.forEach(item->{
//                    if (!"null".equals(item)) {
//                        User user1 = JSONArray.parseObject(item, User.class);
//                        if (Objects.equals(user.getId(), user1.getId())) {
//                            ops.set("UserList", index[0], JSONArray.toJSONString(user));
//                        }
//                    }
//                    index[0]++;
//                });
//            }
            return ResultTool.success("修改用户信息成功");
        }
    }

    /**
     * 删除用户信息
     *
     * @param id
     * @return
     */
    @CacheEvict(cacheNames = "UserList",key = "#id",allEntries = true)
    public JsonResult deleteUser(String id) {
        boolean b = removeById(id);
        if (!b) {
            throw new UserUpdateException("删除用户信息失败");
        } else {
//
//            //            将修改的数据加入Redis缓存中
//            ListOperations<String, String> ops = stringRedisTemplate.opsForList();
//            List<String> list = ops.range("UserList", 0, -1);
//            if (list!=null){
//                list.forEach(item->{
//                    if (!"null".equals(item)) {
//                        User user1 = JSONArray.parseObject(item, User.class);
//                        if (Objects.equals(id, user1.getId())) {
//                            ops.remove("UserList", 1, item);
//                        }
//                    }
//                });
//            }
            return ResultTool.success("删除用户信息成功");
        }
    }

    /**
     * 登陆方法
     *
     * @param username
     * @param password
     * @return
     */
    @Override
    public JsonResult findUserInUsers(String username, String password) {
//        1.查看账号存在与否
        User user = findUserName(username);
//        2.检查密码
        String sqlpassword = user.getPassword();
        String inputpassword = MD5Util.encryptMD5(password);
        boolean b = sqlpassword.equals(inputpassword);
        if (!b) {
            throw new PasswordExpiredException("密码不正确");
        }
//        3.获取权限
        List<Power> powers = findPowerByUserId(user.getId());
        user.setPowers(powers);
//        3.5. 归类
        List<Role> roles = getAndSetRoles(powers);
        user.setRoles(roles);

//        4.将用户信息传递给前端
        request.getSession().setAttribute("BACKEN_User", user);
        return ResultTool.success(user);
    }

    /**
     * 验证后端user数据是否存在
     *
     * @param id
     * @return
     */
    @Override
    public JsonResult isLogin(String id) {
        Object user = request.getSession().getAttribute("BACKEN_User");
        if (user == null) {
            throw new UserNotFoundException("后端user数据不存在");
        }
        User user1 = (User) user;
        if (!user1.getId().equals(id)) {
            throw new UserNotLoginException("用户没有登陆");
        }
        return ResultTool.success(user1);
    }

    /**
     * 生成令牌
     *
     * @param username
     * @return
     */
    public JsonResult getJwtToken(String username) {
        //生成令牌
        User user = findUserName(username);
        String jwtToken = JwtConfig.getJwtToken(user);
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.set("token" + user.getId(), jwtToken,1, TimeUnit.DAYS);
        return ResultTool.success(jwtToken);
    }

    /**
     * 判断令牌是否存在
     *
     * @param token
     * @return
     */
    public JsonResult IsLogin(String token) {
        boolean b = JwtConfig.checkToken(token);
        if (!b) {
            throw new UserNotFoundException("后端令牌数据不存在");
        }
        Claims claims = JwtConfig.parseJWT(token);
        Object userId = claims.get("id");
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        String s = ops.get("token" + userId);
        if (s == null) {
            throw new UserNotFoundException("后端令牌数据不存在");
        }
        if (!Objects.equals(s, token)) {
            throw new UserNotFoundException("后端令牌数据不存在");
        }
        return ResultTool.success(claims.get("username"));
    }

    /**
     * 令牌退出
     *
     * @param token
     * @return
     */
    public JsonResult Loginout(String token) {
        boolean b = JwtConfig.checkToken(token);
        if (!b) {
            return ResultTool.fail(204, "退出失败");
        }
        Claims claims = JwtConfig.parseJWT(token);
        Object userId = claims.get("id");
        Boolean deleted = stringRedisTemplate.delete("token" + userId);
        if (!deleted) {
            return ResultTool.fail(204, "退出失败");
        }
        return ResultTool.success("success");
    }


    /**
     * 验证用户是否存在
     *
     * @param username
     * @return
     */
    public User findUserName(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.eq("username", username);
        wrapper.eq("status", 1);
        User user = getOne(wrapper);
        if (user == null) {
            throw new UserNotFoundException("用户不存在");
        }
        return user;
    }

    /**
     * 通过user_id查询权限
     *
     * @param userId
     * @return
     */
    public List<Power> findPowerByUserId(String userId) {
        List<Power> powers = powerMapper.FindPowersToUser(userId);
        return powers;
    }

    /**
     * 分类归类
     *
     * @param powers
     * @return
     */
    public List<Role> getAndSetRoles(List<Power> powers) {
//        1.创建数组
        ArrayList<Role> roles = new ArrayList<>();
//        2.遍历数据
        for (Power power : powers) {
//            3.状态为0则排除
            if (power.getStatus() == 0) {
                continue;
            }
//            4.获取数据的类型名
            String typeName = power.getTypeName();
            boolean flag = false;
//            5.遍历创建的数组，并比较类型名是否一致（一致则添加，否则跳出）
            for (Role role : roles) {
                if (role.getName().equals(typeName)) {
                    role.getPowers().add(power);
                    flag = true;
                    break;
                }
            }
//            6.不一致则创建一个二级数组添加进之前数组下
            if (!flag) {
                Role role = new Role();
                role.setName(typeName);
                ArrayList<Power> powerArrayList = new ArrayList<>();
                powerArrayList.add(power);
                role.setPowers(powerArrayList);
                roles.add(role);
            }
        }
        return roles;
    }
}
